/*******************************************************************************
 * Copyright (c) 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package de.devisnik.eidle.presentation;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IStackPresentationSite;
import org.eclipse.ui.presentations.StackDropResult;
import org.eclipse.ui.presentations.StackPresentation;

/**
 * @author ELEV se org.eclipse.ui.examples.presentation.sidewinder
 * 
 */
public class Presentation extends StackPresentation {

	/**
	 * part data key.
	 */
	private static final String PART_DATA = "part";

	/**
	 * active focus?
	 */
	private boolean activeFocus = false;

	/**
	 * Main widget for the presentation.
	 */
	private final Composite presentationControl;

	/**
	 * client area.
	 */
	private final Composite itsClientArea;

	/**
	 * content area.
	 */
	private final ViewForm contentArea;

	/**
	 * Currently selected part.
	 */
	private IPresentablePart current;

	/**
	 * @param parent
	 *            parent
	 * @param stackSite
	 *            stack
	 * @param showText
	 *            show text?
	 * @param showImage
	 *            show image?
	 * @param style
	 *            swt style
	 */
	public Presentation(final Composite parent,
			final IStackPresentationSite stackSite, final boolean showText,
			final boolean showImage, final int style) {
		super(stackSite);

		// Create a top-level control for the presentation.
		this.presentationControl = new Composite(parent, SWT.NONE);
		this.presentationControl.setBackground(parent.getDisplay()
				.getSystemColor(SWT.COLOR_CYAN));

		this.contentArea = new ViewForm(this.presentationControl, SWT.NONE);
		this.itsClientArea = new Composite(this.contentArea, SWT.NONE);
		this.itsClientArea.setVisible(false);

		this.contentArea.setContent(this.itsClientArea);

		// Add a dispose listener. This will call the presentationDisposed()
		// method when the widget is destroyed.
		this.presentationControl.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(final DisposeEvent e) {
				presentationDisposed();
			}
		});

		this.presentationControl.addPaintListener(new PaintListener() {
			public void paintControl(final PaintEvent e) {
				final int borderWidth = getBorderWidth();
				final Rectangle clientArea = Presentation.this.presentationControl
						.getClientArea();
				e.gc.setLineWidth(borderWidth);
				if (Presentation.this.activeFocus) {
					e.gc
							.setForeground(e.display
									.getSystemColor(SWT.COLOR_BLUE));
				} else {
					e.gc.setForeground(e.display
							.getSystemColor(SWT.COLOR_DARK_GRAY));
				}
				e.gc.drawRectangle(clientArea.x, clientArea.y,
						clientArea.width, clientArea.height);
			}
		});
		update();
	}

	/**
	 * @return current part
	 */
	public IPresentablePart getCurrent() {
		return this.current;
	}

	/**
	 * handles disposing.
	 */
	protected void presentationDisposed() {
		// Remove any listeners that were attached to any
		// global Eclipse resources. This is necessary in order to prevent
		// memory leaks.
	}

	/**
	 * @return border width
	 */
	protected int getBorderWidth() {
		return 0;
	}

	/**
	 * update.
	 */
	protected void update() {
		layout();
		this.presentationControl.redraw();
	}

	/**
	 * layout.
	 */
	public void layout() {
		// Determine the inner bounds of the presentation
		final Rectangle presentationClientArea = this.presentationControl
				.getClientArea();
		presentationClientArea.x += getBorderWidth();
		presentationClientArea.width -= getBorderWidth() * 2;
		presentationClientArea.y += getBorderWidth();
		presentationClientArea.height -= getBorderWidth() * 2;

		this.contentArea.setBounds(presentationClientArea.x,
				presentationClientArea.y, presentationClientArea.width,
				presentationClientArea.height);

		// Position the view's widgets
		if (this.current != null) {
			this.contentArea.layout();

			final Rectangle clientRectangle = this.itsClientArea.getBounds();
			final Point clientAreaStart = this.presentationControl.getParent()
					.toControl(
							this.contentArea.toDisplay(clientRectangle.x,
									clientRectangle.y));
			// current isn't parented by this widget hierarchy, the coordinates
			// must be
			// relative to the workbench window. The workbench window parents
			// every
			// part.
			this.current.setBounds(new Rectangle(clientAreaStart.x,
					clientAreaStart.y, clientRectangle.width,
					clientRectangle.height));
		}
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public void setBounds(final Rectangle bounds) {
		this.presentationControl.setBounds(bounds);
		layout();
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public void dispose() {
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public void setActive(final int newState) {
		this.activeFocus = (newState == AS_ACTIVE_FOCUS);
		this.presentationControl.redraw();
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public void setVisible(final boolean isVisible) {
		this.presentationControl.setVisible(isVisible);

		// Make the currently visible part visible
		if (this.current != null) {
			this.current.setVisible(isVisible);
		}

		if (isVisible) {
			// Restore the bounds of the currently visible part.
			// IPartPresentations can be used by multiple StackPresentations,
			// although only one such presentation is ever visible at a time.
			// It is possible that some other presentation has changed the
			// bounds of the part since it was last visible, so we need to
			// update the part's bounds when the presentation becomes visible.
			layout();
		}
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public void setState(final int state) {
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public Control getControl() {
		return this.presentationControl;
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public void addPart(final IPresentablePart newPart, final Object cookie) {
	}

	/**
	 * get part for tab.
	 * 
	 * @param item
	 *            item
	 * @return part
	 */
	protected final IPresentablePart getPartForTab(final Control item) {
		return (IPresentablePart) item.getData(PART_DATA);
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public void removePart(final IPresentablePart oldPart) {
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public void selectPart(final IPresentablePart toSelect) {
		if (toSelect == this.current) {
			return;
		}

		if (this.current != null) {
			this.current.setVisible(false);
		}

		// Select the new part
		this.current = toSelect;

		// Ordering is important here. We need to make the part
		// visible before updating its bounds, or the call to setBounds
		// may be ignored.

		if (this.current != null) {
			// Make the newly selected part visible
			this.current.setVisible(true);
		}
		// Update the bounds of the newly selected part
		layout();
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public StackDropResult dragOver(final Control currentControl,
			final Point location) {
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public void showSystemMenu() {
	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public void showPaneMenu() {

	}

	/**
	 * {@inheritDoc}
	 */
	// @Override
	public Control[] getTabList(final IPresentablePart part) {
		if (this.current != null) {
			return new Control[] { this.current.getControl() };
		} else {
			return new Control[0];
		}
	}
}
